package com.itbac.j2cache.aop.aspect;

import com.google.gson.Gson;
import com.itbac.j2cache.aop.annotatin.J2CacheEvict;
import com.itbac.j2cache.aop.annotatin.J2CachePut;
import com.itbac.j2cache.aop.annotatin.J2Cacheable;
import com.itbac.j2cache.aop.generator.DefaultKeyGenerator;
import com.itbac.j2cache.client.J2CacheClient;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * @description 切面类 ,解析注解，操作缓存。
 * 用于自定义缓存注解：
 * com.itbac.j2cache.aop.annotatin.J2Cacheable
 * com.itbac.j2cache.aop.annotatin.J2CacheEvict
 * com.itbac.j2cache.aop.annotatin.J2CachePut
 *
 * @author itbac
 * @email 1218585258@qq.com
 * @date 2020/6/17
 */
@Aspect
@Component
public class J2CacheAspect {
    private static Logger logger = LoggerFactory.getLogger(J2CacheAspect.class);
    @Autowired
    private J2CacheClient j2CacheClient;
    @Autowired
    private DefaultKeyGenerator defaultKeyGenerator;
    private Gson gson = new Gson();

    /**
     * 环绕通知
     * @param
     * @return
     */
    @Around("@annotation(j2Cacheable)")
    public Object j2Cacheable(final ProceedingJoinPoint pjp,J2Cacheable j2Cacheable) throws Throwable {
        String key = defaultKeyGenerator.generateKey(pjp, j2Cacheable.cacheName(), j2Cacheable.cacheKey());
        Class clazz = j2Cacheable.clazz();
        int expire = j2Cacheable.expire();
        String value = j2CacheClient.getValue(key);
        if (!StringUtils.isEmpty(value)) {
            if (clazz.equals(String.class)) {
                //返回字符串
                return value;
            }else {
                //返回对象
                return gson.fromJson(value, clazz);
            }
        }
        //查询数据库结果
        Object proceed = pjp.proceed();
        if (null != proceed) {
            setValue(proceed, expire, clazz, key);
        }
        return proceed;
    }
    @Around("@annotation(j2CacheEvict)")
    public Object j2CacheEvict(final ProceedingJoinPoint pjp,J2CacheEvict j2CacheEvict) throws Throwable {
        String key = defaultKeyGenerator.generateKey(pjp, j2CacheEvict.cacheName(), j2CacheEvict.cacheKey());
        Object proceed = pjp.proceed();
        if(!StringUtils.isEmpty(key)){
            //删除redis缓存 ,删除本地缓存
            j2CacheClient.delKey(key, true);
        }
        return proceed;
    }
    @Around("@annotation(j2CachePut)")
    public Object j2CachePut(final ProceedingJoinPoint pjp,J2CachePut j2CachePut) throws Throwable {
        Object proceed = pjp.proceed();
        int expire = j2CachePut.expire();
        Class clazz = j2CachePut.clazz();
        String key = defaultKeyGenerator.generateKey(pjp, j2CachePut.cacheName(), j2CachePut.cacheKey());
        if (!StringUtils.isEmpty(key)) {
            if (null !=proceed){
                setValue(proceed, expire, clazz, key);
                //删除本地缓存
                j2CacheClient.delLocalKey(key, true);
            }
        }
        return proceed;
    }

    /**
     * 设置数据到Redis缓存
     * @param proceed 结果数据
     * @param expire 过期时间
     * @param clazz 数据类型
     * @param key 缓存key
     */
    private void setValue(Object proceed, int expire, Class clazz, String key) {
        if (clazz.equals(String.class)) {
            //设置Redis缓存
            //设置字符串
            if(0<expire){
                j2CacheClient.set(key, String.valueOf(proceed),expire);
            }else {
                j2CacheClient.set(key, String.valueOf(proceed));
            }
        }else {
            //设置Redis缓存
            //转json 再设置
            if(0<expire){
                j2CacheClient.set(key, gson.toJson(proceed),expire);
            }else {
                j2CacheClient.set(key, gson.toJson(proceed));
            }
        }
    }


}
